﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Exceptions;
using UtilZ.Dotnet.Ex.Model;
using UtilZ.Dotnet.Ex.ZLog;


namespace UtilZ.Dotnet.Ex.DataStruct
{
#pragma warning disable 8500

    /// <summary>
    /// 数据拼接器,非线程安全.仅当数据类型为结构体时,才可调用指针参数相关的函数
    /// </summary>
    [DebuggerTypeProxy(typeof(ValueTypeDataMergerDebugView<>))]
    [DebuggerDisplay("Length = {Length}")]
    unsafe public class ValueTypeDataMerger<T> : IDisposable
         where T : struct
    {
        private readonly ValueTypeDataMergerOptions _options;
        /// <summary>
        /// 获取实例初始化选项
        /// </summary>
        public ValueTypeDataMergerOptions Options
        {
            get { return this._options; }
        }


        private T* _dataPtr = null;
        private readonly long _TSize;
        private long _capcity = 0;
        private long _length = 0;
        private long _writeIndex = 0;
        private long _readIndex = 0;


        /// <summary>
        /// 获取数据长度
        /// </summary>
        public int Length
        {
            get
            {
                if (this._length > int.MaxValue)
                {
                    return int.MaxValue;
                }
                else
                {
                    return (int)this._length;
                }
            }
        }

        /// <summary>
        /// 获取数据长度
        /// </summary>
        public long LongLength
        {
            get { return _length; }
        }





        /// <summary>
        /// 
        /// </summary>
        /// <param name="options">数据拼接器选项,为null时使用默认值</param>
        public ValueTypeDataMerger(ValueTypeDataMergerOptions options = null)
        {
            if (options == null)
            {
                options = new ValueTypeDataMergerOptions();
            }

            this._options = options;

            //if (options.LimitCapcity > 0)
            //{
            //    //固定容量上限
            //    this._capcity = options.LimitCapcity;
            //}
            //else
            //{
            if (options.InitCapcity > 0)
            {
                this._capcity = options.InitCapcity;
            }
            else
            {
                this._capcity = 1000;
            }
            //}

            this._TSize = sizeof(T);
            this._dataPtr = (T*)NativeMemory.Alloc((nuint)(this._capcity * this._TSize));
        }





        /// <summary>
        /// 追加数据,返回追加成功的数据长度
        /// </summary>
        /// <param name="buffer">数据buffer</param>
        /// <returns>追加成功的数据长度</returns>
        public int Append(T[] buffer)
        {
            if (buffer == null || buffer.Length == 0)
            {
                return 0;
            }

            fixed (T* ptr = buffer)
            {
                return (int)this.PrimitiveAppend(ptr, buffer.Length);
            }
        }

        /// <summary>
        /// 追加数据,返回追加成功的数据长度
        /// </summary>
        /// <param name="buffer">数据buffer</param>
        /// <param name="offset">数据buffer起始位置</param>
        /// <param name="length">要追加的数据buffer长度</param>
        /// <returns>追加成功的数据长度</returns>
        public int Append(T[] buffer, int offset, int length)
        {
            if (buffer == null || buffer.Length == 0)
            {
                return 0;
            }

            if (offset < 0 || offset >= buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            if (length < 0 || offset + length > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            fixed (T* ptr = buffer)
            {
                return (int)this.PrimitiveAppend(ptr + offset, length);
            }
        }

        /// <summary>
        /// 追加数据,返回追加成功的数据长度
        /// </summary>
        /// <param name="buffer">数据buffer</param>
        /// <param name="offset">数据buffer起始位置</param>
        /// <param name="length">要追加的数据buffer长度</param>
        /// <returns>追加成功的数据长度</returns>
        public long Append(T[] buffer, long offset, long length)
        {
            if (buffer == null || buffer.Length == 0)
            {
                return 0;
            }

            if (offset < 0 || offset >= buffer.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            if (length < 0 || offset + length > buffer.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            fixed (T* ptr = buffer)
            {
                return this.PrimitiveAppend(ptr + offset, length);
            }
        }

        /// <summary>
        /// 追加数据,返回追加成功的数据长度
        /// </summary>
        /// <param name="span">Span数据</param>
        /// <returns>追加成功的数据长度</returns>
        public int Append(in Span<T> span)
        {
            T* ptr = UnmanagedMemoryHelper.GetSpanPointer(span);
            return (int)this.PrimitiveAppend(ptr, span.Length);
        }

        /// <summary>
        /// 追加数据,返回追加成功的数据长度
        /// </summary>
        /// <param name="span">Span数据</param>
        /// <returns>追加成功的数据长度</returns>
        public long Append(in SpanZ<T> span)
        {
            return this.PrimitiveAppend(span.DataPtr, span.LongLength);
        }

        /// <summary>
        /// 追加数据,返回追加成功的数据长度
        /// </summary>
        /// <param name="ptr">数据指针</param>
        /// <param name="length">追加数据长度</param>
        /// <returns>追加成功的数据长度</returns>
        public int Append(T* ptr, int length)
        {
            return (int)this.PrimitiveAppend(ptr, length);
        }

        /// <summary>
        /// 追加数据,返回追加成功的数据长度
        /// </summary>
        /// <param name="ptr">数据指针</param>
        /// <param name="length">追加数据长度</param>
        /// <returns>追加成功的数据长度</returns>
        public long Append(T* ptr, long length)
        {
            return this.PrimitiveAppend(ptr, length);
        }



        private long PrimitiveAppend(T* ptr, long length)
        {
            if (length <= 0)
            {
                return 0L;
            }

            if (this._length + length > this._capcity)
            {
                //数组剩余空间不足，需要扩容
                long sourceOffet = this.ExtendCapacity(in length);
                if (sourceOffet < 0)
                {
                    //忽略数据追加
                    return 0L;
                }

                if (sourceOffet > 0)
                {
                    //调整要追加的原数据起始位置及长度
                    ptr = ptr + sourceOffet;
                    length -= sourceOffet;
                }
            }

            var byteLength = this._TSize * length;

            long modLength = this._capcity - this._writeIndex;
            if (modLength >= length)
            {
                //数据当前写索引之后空余空间长度足够
                NativeMemory.Copy(ptr, this._dataPtr + this._writeIndex, (nuint)byteLength);
                this._writeIndex += length;
            }
            else
            {
                //数据当前写索引之后空余空间长度不够
                //先写空余空间
                var modByteLength = this._TSize * modLength;
                NativeMemory.Copy(ptr, this._dataPtr + this._writeIndex, (nuint)modByteLength);

                //将写位置归0，重新从0开始写
                var modWriteLength = byteLength - modByteLength;
                NativeMemory.Copy(ptr + modLength, this._dataPtr, (nuint)modWriteLength);
                this._writeIndex = length - modLength;
            }

            this._length += length;
            return length;
        }


        /// <summary>
        /// 扩展容器,返回值:小于0表示忽略新追加的数据,等于0表示直接追加,大于0表示要追加的数据需要进行起始位置偏移操作
        /// </summary>
        /// <param name="newDataLength"></param>
        /// <returns></returns>
        private long ExtendCapacity(in long newDataLength)
        {
            long sourceOffet = 0L, newCapcity;

            //计算得到新容量值
            long requireLength = this._length + newDataLength;
            if (requireLength < this._options.Limit)
            {
                //当缓存容量小于门限时，每次扩容直接乘以扩展系数
                newCapcity = (long)(requireLength * this._options.Factor);
            }
            else
            {
                //当缓存容量大于门限时，每次扩容直接乘以门限扩展系数
                newCapcity = (long)(requireLength * this._options.LimitFactor);
            }


            if (this._options.LimitCapcity > 0)
            {
                //有容量上限
                if (newCapcity > this._options.LimitCapcity)
                {
                    //新容量超出了上限,则将新容量设置为上限值.
                    newCapcity = this._options.LimitCapcity;
                }

                if (newCapcity <= newDataLength)
                {
                    //test 1
                    //如果新容量小于等于新数据长度,则截取新数据,以及清空旧数据
                    sourceOffet = newDataLength - newCapcity;
                    this.Clear();
                }
                else
                {
                    //如果新容量大于新数据长度,
                    if (newCapcity - this._length < newDataLength)
                    {
                        //test 2
                        //如果 新容量 - 已有数据长度 < 新数据长度,则移除部分已有数据                            
                        this.ContainerFull(this._capcity, newDataLength + this._length - newCapcity);
                    }
                    else
                    {
                        //test 3
                        //如果 新容量 - 已有数据长度 >= 新数据长度,则不作操作
                    }
                }

                if (newCapcity <= this._capcity)
                {
                    return sourceOffet;
                }
            }


            //调整内存空间大小
            nuint newCapcityByteLength = new nuint((ulong)(newCapcity * this._TSize));
            void* newPtr;
            if (this._dataPtr == null)
            {
                newPtr = NativeMemory.Alloc(newCapcityByteLength);

                if (newPtr == null)
                {
                    throw new AccessViolationException($"从{this._capcity}->{newCapcity}申请内存失败,申请内存字节数{newCapcityByteLength}");
                }
            }
            else
            {
                newPtr = NativeMemory.Realloc(this._dataPtr, newCapcityByteLength);

                if (newPtr == null)
                {
                    throw new AccessViolationException($"从{this._capcity}->{newCapcity}扩展内存失败,扩展内存字节数{newCapcityByteLength}");
                }
            }

            this._dataPtr = (T*)newPtr;
            this._capcity = newCapcity;

            return sourceOffet;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="capcity">当前容量</param>
        /// <param name="dropLength"></param>
        /// <returns>返回true表示忽略新追加的数制;false表示继续追加</returns>
        /// <exception cref="ContainerFullException"></exception>
        /// <exception cref="NotImplementedException"></exception>
        private bool ContainerFull(long capcity, long dropLength)
        {
            switch (this._options.FullMode)
            {
                case ContainerFullMode.Exception:
                    throw new ContainerFullException();
                case ContainerFullMode.DropNew:
                    if (this._writeIndex >= dropLength)
                    {
                        this._writeIndex -= dropLength;
                    }
                    else
                    {
                        this._writeIndex = capcity - (dropLength - this._writeIndex);
                    }

                    this._length -= dropLength;
                    break;
                case ContainerFullMode.DropOld:
                    long modLength = capcity - this._readIndex;
                    if (modLength >= dropLength)
                    {
                        this._readIndex += dropLength;
                    }
                    else
                    {
                        this._readIndex = dropLength - modLength;
                    }

                    this._length -= dropLength;
                    break;
                case ContainerFullMode.Ignore:
                    //直接返回即可
                    ZLoger.Warn($"{nameof(ValueTypeDataMerger<T>)}忽略数据项");
                    return true;
                default:
                    throw new NotImplementedException(this._options.FullMode.ToString());
            }

            return false;
        }







        private T* _takePtr = null;
        private long _takePtrLength = 0L;

        private void CheckTakePtr(long length, nuint byteLength)
        {
            if (this._takePtrLength >= length)
            {
                return;
            }

            //检查需要首尾拼接的span内存长度是否足够,不够就扩容
            if (this._takePtrLength == 0)
            {
                this._takePtr = (T*)NativeMemory.Alloc(byteLength);
            }
            else
            {
                void* newPtr = NativeMemory.Realloc(this._takePtr, byteLength);
                if (newPtr == null)
                {
                    throw new ArgumentException("申请内存失败");
                }
                this._takePtr = (T*)newPtr;
            }
        }

        #region Take

        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public Span<T> TakeSpan(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                Span<T> result = new Span<T>(this._dataPtr + this._readIndex, length);
                this._readIndex += length;
                this._length -= length;
                return result;
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            //检查take指针容量
            this.CheckTakePtr(length, byteLength);

            nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
            //先读取数组后面的
            NativeMemory.Copy(this._dataPtr + this._readIndex, this._takePtr, modByteLength);

            //读取位置归0，再重头读取剩余长度的数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + modLength, byteLength - modByteLength);

            this._readIndex = length - modLength;
            this._length -= length;
            return new Span<T>(this._takePtr, length);
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public Span<T> TakeTailSpan(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (this._writeIndex >= length)
            {
                Span<T> result = new Span<T>(this._dataPtr + this._writeIndex - length, length);
                this._writeIndex -= length;
                this._length -= length;
                return result;
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            //检查take指针容量
            this.CheckTakePtr(length, byteLength);

            long secondPartLength = this._writeIndex;
            nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
            long firstPartLength = length - secondPartLength;

            //先读取第二部分数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + firstPartLength, secondPartByteLength);

            //再读第一部分数据
            NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, this._takePtr, byteLength - secondPartByteLength);

            this._writeIndex = this._capcity - firstPartLength;
            this._length -= length;
            return new Span<T>(this._takePtr, length);
        }




        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public SpanZ<T> TakeSpanZ(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                SpanZ<T> result = new SpanZ<T>(this._dataPtr + this._readIndex, length);
                this._readIndex += length;
                this._length -= length;
                return result;
            }


            nuint byteLength = new nuint((ulong)(length * this._TSize));
            //检查take指针容量
            this.CheckTakePtr(length, byteLength);

            nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
            //先读取数组后面的
            NativeMemory.Copy(this._dataPtr + this._readIndex, this._takePtr, modByteLength);

            //读取位置归0，再重头读取剩余长度的数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + modLength, byteLength - modByteLength);

            this._readIndex = length - modLength;
            this._length -= length;
            return new SpanZ<T>(this._takePtr, length);
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public SpanZ<T> TakeTailSpanZ(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (this._writeIndex >= length)
            {
                SpanZ<T> result = new SpanZ<T>(this._dataPtr + this._writeIndex - length, length);
                this._writeIndex -= length;
                this._length -= length;
                return result;
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            //检查take指针容量
            this.CheckTakePtr(length, byteLength);

            long secondPartLength = this._writeIndex;
            nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
            long firstPartLength = length - secondPartLength;

            //先读取第二部分数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + firstPartLength, secondPartByteLength);

            //再读第一部分数据            
            NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, this._takePtr, byteLength - secondPartByteLength);

            this._writeIndex = this._capcity - firstPartLength;
            this._length -= length;
            return new SpanZ<T>(this._takePtr, length);
        }




        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public SpanZ<T> TakeSpanZ(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                SpanZ<T> result = new SpanZ<T>(this._dataPtr + this._readIndex, length);
                this._readIndex += length;
                this._length -= length;
                return result;
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            //检查take指针容量
            this.CheckTakePtr(length, byteLength);

            nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
            //先读取数组后面的
            NativeMemory.Copy(this._dataPtr + this._readIndex, this._takePtr, modByteLength);

            //读取位置归0，再重头读取剩余长度的数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + modLength, byteLength - modByteLength);

            this._readIndex = length - modLength;
            this._length -= length;
            return new SpanZ<T>(this._takePtr, length);
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public SpanZ<T> TakeTailSpanZ(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (this._writeIndex >= length)
            {
                SpanZ<T> result = new SpanZ<T>(this._dataPtr + this._writeIndex - length, length);
                this._writeIndex -= length;
                this._length -= length;
                return result;
            }


            nuint byteLength = new nuint((ulong)(length * this._TSize));
            //检查take指针容量
            this.CheckTakePtr(length, byteLength);

            long secondPartLength = this._writeIndex;
            nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
            long firstPartLength = length - secondPartLength;

            //先读取第二部分数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + firstPartLength, secondPartByteLength);

            //再读第一部分数据            
            NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, this._takePtr, byteLength - secondPartByteLength);

            this._writeIndex = this._capcity - firstPartLength;
            this._length -= length;
            return new SpanZ<T>(this._takePtr, length);
        }




        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns>数据</returns>
        public T[] Take(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            var data = new T[length];

            fixed (T* ptr = data)
            {
                long modLength = this._capcity - this._readIndex;
                if (modLength >= length)
                {
                    //从读取位置到结尾足够
                    NativeMemory.Copy(this._dataPtr + this._readIndex, ptr, byteLength);
                    this._readIndex += length;
                }
                else
                {
                    nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                    //先读取数组后面的
                    NativeMemory.Copy(this._dataPtr + this._readIndex, ptr, modByteLength);

                    //读取位置归0，再重头读取剩余长度的数据
                    NativeMemory.Copy(this._dataPtr, ptr + modLength, byteLength - modByteLength);
                    this._readIndex = length - modLength;
                }
            }

            this._length -= length;
            return data;
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns>数据</returns>
        public T[] TakeTail(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            var data = new T[length];

            fixed (T* ptr = data)
            {
                if (this._writeIndex >= length)
                {
                    var startIndex = this._writeIndex - length;
                    NativeMemory.Copy(this._dataPtr + startIndex, ptr, byteLength);
                    this._writeIndex = startIndex;
                }
                else
                {
                    long secondPartLength = this._writeIndex;
                    nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                    long firstPartLength = length - secondPartLength;

                    //先读取第二部分数据
                    NativeMemory.Copy(this._dataPtr, ptr + firstPartLength, secondPartByteLength);

                    //再读第一部分数据
                    NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, ptr, byteLength - secondPartByteLength);
                    this._writeIndex = this._capcity - firstPartLength;
                }
            }

            this._length -= length;
            return data;
        }




        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns>数据</returns>
        public T[] Take(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            var data = new T[length];

            fixed (T* ptr = data)
            {
                long modLength = this._capcity - this._readIndex;
                if (modLength >= length)
                {
                    //从读取位置到结尾足够
                    NativeMemory.Copy(this._dataPtr + this._readIndex, ptr, byteLength);
                    this._readIndex += length;
                }
                else
                {
                    nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                    //先读取数组后面的
                    NativeMemory.Copy(this._dataPtr + this._readIndex, ptr, modByteLength);

                    //读取位置归0，再重头读取剩余长度的数据
                    NativeMemory.Copy(this._dataPtr, ptr + modLength, byteLength - modByteLength);
                    this._readIndex = length - modLength;
                }
            }

            this._length -= length;
            return data;
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns>数据</returns>
        public T[] TakeTail(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            var data = new T[length];

            fixed (T* ptr = data)
            {
                if (this._writeIndex >= length)
                {
                    var startIndex = this._writeIndex - length;
                    NativeMemory.Copy(this._dataPtr + startIndex, ptr, byteLength);
                    this._writeIndex = startIndex;
                }
                else
                {
                    long secondPartLength = this._writeIndex;
                    nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                    long firstPartLength = length - secondPartLength;

                    //先读取第二部分数据
                    NativeMemory.Copy(this._dataPtr, ptr + firstPartLength, secondPartByteLength);

                    //再读第一部分数据            
                    NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, ptr, byteLength - secondPartByteLength);

                    this._writeIndex = this._capcity - firstPartLength;
                }
            }

            this._length -= length;
            return data;
        }





        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="destinationArray">目标数组</param>
        /// <param name="destinationIndex">目标数组起始位置</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void Take(T[] destinationArray, int destinationIndex, int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationArray == null)
            {
                throw new ArgumentNullException(nameof(destinationArray));
            }

            if (destinationIndex >= destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            long endIndex = (long)destinationIndex + (long)length;
            if (endIndex > destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));

            fixed (T* ptr = destinationArray)
            {
                T* destPtr = ptr + destinationIndex;
                long modLength = this._capcity - this._readIndex;
                if (modLength >= length)
                {
                    //从读取位置到结尾足够
                    NativeMemory.Copy(this._dataPtr + this._readIndex, destPtr, byteLength);
                    this._readIndex += length;
                }
                else
                {
                    nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                    //先读取数组后面的
                    NativeMemory.Copy(this._dataPtr + this._readIndex, destPtr, modByteLength);

                    //读取位置归0，再重头读取剩余长度的数据
                    NativeMemory.Copy(this._dataPtr, ptr + modLength, byteLength - modByteLength);
                    this._readIndex = length - modLength;
                }
            }

            this._length -= length;
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="destinationArray">目标数组</param>
        /// <param name="destinationIndex">目标数组起始位置</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void TakeTail(T[] destinationArray, int destinationIndex, int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationArray == null)
            {
                throw new ArgumentNullException(nameof(destinationArray));
            }

            if (destinationIndex >= destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            long endIndex = (long)destinationIndex + (long)length;
            if (endIndex > destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));

            fixed (T* ptr = destinationArray)
            {
                T* destPtr = ptr + destinationIndex;
                if (this._writeIndex >= length)
                {
                    var startIndex = this._writeIndex - length;
                    NativeMemory.Copy(this._dataPtr + startIndex, destPtr, byteLength);
                    this._writeIndex = startIndex;
                }
                else
                {
                    long secondPartLength = this._writeIndex;
                    nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                    long firstPartLength = length - secondPartLength;

                    //先读取第二部分数据
                    NativeMemory.Copy(this._dataPtr, destPtr + firstPartLength, secondPartByteLength);

                    //再读第一部分数据
                    NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, destPtr, byteLength - secondPartByteLength);
                    this._writeIndex = this._capcity - firstPartLength;
                }
            }

            this._length -= length;
        }





        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="destinationArray">目标数组</param>
        /// <param name="destinationIndex">目标数组起始位置</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void Take(T[] destinationArray, long destinationIndex, long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationArray == null)
            {
                throw new ArgumentNullException(nameof(destinationArray));
            }

            if (destinationIndex >= destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            long endIndex = (long)destinationIndex + (long)length;
            if (endIndex > destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));

            fixed (T* ptr = destinationArray)
            {
                T* destPtr = ptr + destinationIndex;
                long modLength = this._capcity - this._readIndex;
                if (modLength >= length)
                {
                    //从读取位置到结尾足够
                    NativeMemory.Copy(this._dataPtr + this._readIndex, destPtr, byteLength);
                    this._readIndex += length;
                }
                else
                {
                    nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                    //先读取数组后面的
                    NativeMemory.Copy(this._dataPtr + this._readIndex, destPtr, modByteLength);

                    //读取位置归0，再重头读取剩余长度的数据
                    NativeMemory.Copy(this._dataPtr, ptr + modLength, byteLength - modByteLength);
                    this._readIndex = length - modLength;
                }
            }

            this._length -= length;
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="destinationArray">目标数组</param>
        /// <param name="destinationIndex">目标数组起始位置</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void TakeTail(T[] destinationArray, long destinationIndex, long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationArray == null)
            {
                throw new ArgumentNullException(nameof(destinationArray));
            }

            if (destinationIndex >= destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            long endIndex = (long)destinationIndex + (long)length;
            if (endIndex > destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));

            fixed (T* ptr = destinationArray)
            {
                T* destPtr = ptr + destinationIndex;
                if (this._writeIndex >= length)
                {
                    var startIndex = this._writeIndex - length;
                    NativeMemory.Copy(this._dataPtr + startIndex, destPtr, byteLength);
                    this._writeIndex = startIndex;
                }
                else
                {
                    long secondPartLength = this._writeIndex;
                    nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                    long firstPartLength = length - secondPartLength;

                    //先读取第二部分数据
                    NativeMemory.Copy(this._dataPtr, destPtr + firstPartLength, secondPartByteLength);

                    //再读第一部分数据            
                    NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, destPtr, byteLength - secondPartByteLength);
                    this._writeIndex = this._capcity - firstPartLength;
                }
            }

            this._length -= length;
        }





        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="destinationPtr">目标指针</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void Take(T* destinationPtr, int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationPtr == null)
            {
                throw new ArgumentNullException(nameof(destinationPtr));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                NativeMemory.Copy(this._dataPtr + this._readIndex, destinationPtr, byteLength);
                this._readIndex += length;
            }
            else
            {
                nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                //先读取数组后面的
                NativeMemory.Copy(this._dataPtr + this._readIndex, destinationPtr, modByteLength);

                //读取位置归0，再重头读取剩余长度的数据
                NativeMemory.Copy(this._dataPtr, destinationPtr + modLength, byteLength - modByteLength);
                this._readIndex = length - modLength;
            }

            this._length -= length;
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="destinationPtr">目标数组</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void TakeTail(T* destinationPtr, int length)
        {
            if (destinationPtr == null)
            {
                throw new ArgumentNullException(nameof(destinationPtr));
            }

            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._writeIndex >= length)
            {
                var startIndex = this._writeIndex - length;
                NativeMemory.Copy(this._dataPtr + startIndex, destinationPtr, byteLength);
                this._writeIndex = startIndex;
            }
            else
            {
                long secondPartLength = this._writeIndex;
                nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                long firstPartLength = length - secondPartLength;

                //先读取第二部分数据
                NativeMemory.Copy(this._dataPtr, destinationPtr + firstPartLength, secondPartByteLength);

                //再读第一部分数据
                NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, destinationPtr, byteLength - secondPartByteLength);

                this._writeIndex = this._capcity - firstPartLength;
            }

            this._length -= length;
        }





        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="destinationPtr">目标指针</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void Take(T* destinationPtr, long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationPtr == null)
            {
                throw new ArgumentNullException(nameof(destinationPtr));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                NativeMemory.Copy(this._dataPtr + this._readIndex, destinationPtr, byteLength);
                this._readIndex += length;
            }
            else
            {
                nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                //先读取数组后面的
                NativeMemory.Copy(this._dataPtr + this._readIndex, destinationPtr, modByteLength);

                //读取位置归0，再重头读取剩余长度的数据
                NativeMemory.Copy(this._dataPtr, destinationPtr + modLength, byteLength - modByteLength);
                this._readIndex = length - modLength;
            }

            this._length -= length;
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="destinationPtr">目标数组</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void TakeTail(T* destinationPtr, long length)
        {
            if (destinationPtr == null)
            {
                throw new ArgumentNullException(nameof(destinationPtr));
            }

            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._writeIndex >= length)
            {
                var startIndex = this._writeIndex - length;
                NativeMemory.Copy(this._dataPtr + startIndex, destinationPtr, byteLength);
                this._writeIndex = startIndex;
            }
            else
            {
                long secondPartLength = this._writeIndex;
                nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                long firstPartLength = length - secondPartLength;

                //先读取第二部分数据
                NativeMemory.Copy(this._dataPtr, destinationPtr + firstPartLength, secondPartByteLength);

                //再读第一部分数据            
                NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, destinationPtr, byteLength - secondPartByteLength);

                this._writeIndex = this._capcity - firstPartLength;
            }

            this._length -= length;
        }

        #endregion



        #region Peek


        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public Span<T> PeekSpan(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                return new Span<T>(this._dataPtr + this._readIndex, length);
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._takePtrLength < length)
            {
                //检查需要首尾拼接的span内存长度是否足够,不够就扩容
                if (this._takePtrLength == 0)
                {
                    this._takePtr = (T*)NativeMemory.Alloc(byteLength);
                }
                else
                {
                    void* newPtr = NativeMemory.Realloc(this._takePtr, byteLength);
                    if (newPtr == null)
                    {
                        throw new ArgumentException("申请内存失败");
                    }
                    this._takePtr = (T*)newPtr;
                }
            }



            nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
            //先读取数组后面的
            NativeMemory.Copy(this._dataPtr + this._readIndex, this._takePtr, modByteLength);

            //读取位置归0，再重头读取剩余长度的数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + modLength, byteLength - modByteLength);
            return new Span<T>(this._takePtr, length);
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public Span<T> PeekTailSpan(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (this._writeIndex >= length)
            {
                return new Span<T>(this._dataPtr + this._writeIndex - length, length);
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._takePtrLength < length)
            {
                //检查需要首尾拼接的span内存长度是否足够,不够就扩容
                if (this._takePtrLength == 0)
                {
                    this._takePtr = (T*)NativeMemory.Alloc(byteLength);
                }
                else
                {
                    void* newPtr = NativeMemory.Realloc(this._takePtr, byteLength);
                    if (newPtr == null)
                    {
                        throw new ArgumentException("申请内存失败");
                    }
                    this._takePtr = (T*)newPtr;
                }
            }

            long secondPartLength = this._writeIndex;
            nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
            long firstPartLength = length - secondPartLength;

            //先读取第二部分数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + firstPartLength, secondPartByteLength);

            //再读第一部分数据
            NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, this._takePtr, byteLength - secondPartByteLength);
            return new Span<T>(this._takePtr, length);
        }




        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public SpanZ<T> PeekSpanZ(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                return new SpanZ<T>(this._dataPtr + this._readIndex, length);
            }


            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._takePtrLength < length)
            {
                //检查需要首尾拼接的span内存长度是否足够,不够就扩容
                if (this._takePtrLength == 0)
                {
                    this._takePtr = (T*)NativeMemory.Alloc(byteLength);
                }
                else
                {
                    void* newPtr = NativeMemory.Realloc(this._takePtr, byteLength);
                    if (newPtr == null)
                    {
                        throw new ArgumentException("申请内存失败");
                    }
                    this._takePtr = (T*)newPtr;
                }
            }



            nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
            //先读取数组后面的
            NativeMemory.Copy(this._dataPtr + this._readIndex, this._takePtr, modByteLength);

            //读取位置归0，再重头读取剩余长度的数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + modLength, byteLength - modByteLength);
            return new SpanZ<T>(this._takePtr, length);
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public SpanZ<T> PeekTailSpanZ(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (this._writeIndex >= length)
            {
                return new SpanZ<T>(this._dataPtr + this._writeIndex - length, length);
            }


            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._takePtrLength < length)
            {
                //检查需要首尾拼接的span内存长度是否足够,不够就扩容
                if (this._takePtrLength == 0)
                {
                    this._takePtr = (T*)NativeMemory.Alloc(byteLength);
                }
                else
                {
                    void* newPtr = NativeMemory.Realloc(this._takePtr, byteLength);
                    if (newPtr == null)
                    {
                        throw new ArgumentException("申请内存失败");
                    }
                    this._takePtr = (T*)newPtr;
                }
            }

            long secondPartLength = this._writeIndex;
            nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
            long firstPartLength = length - secondPartLength;

            //先读取第二部分数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + firstPartLength, secondPartByteLength);

            //再读第一部分数据            
            NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, this._takePtr, byteLength - secondPartByteLength);
            return new SpanZ<T>(this._takePtr, length);
        }




        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public SpanZ<T> PeekSpanZ(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                return new SpanZ<T>(this._dataPtr + this._readIndex, length);
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._takePtrLength < length)
            {
                //检查需要首尾拼接的span内存长度是否足够,不够就扩容
                if (this._takePtrLength == 0)
                {
                    this._takePtr = (T*)NativeMemory.Alloc(byteLength);
                }
                else
                {
                    void* newPtr = NativeMemory.Realloc(this._takePtr, byteLength);
                    if (newPtr == null)
                    {
                        throw new ArgumentException("申请内存失败");
                    }
                    this._takePtr = (T*)newPtr;
                }
            }

            nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
            //先读取数组后面的
            NativeMemory.Copy(this._dataPtr + this._readIndex, this._takePtr, modByteLength);

            //读取位置归0，再重头读取剩余长度的数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + modLength, byteLength - modByteLength);
            return new SpanZ<T>(this._takePtr, length);
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public SpanZ<T> PeekTailSpanZ(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (this._writeIndex >= length)
            {
                return new SpanZ<T>(this._dataPtr + this._writeIndex - length, length);
            }


            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._takePtrLength < length)
            {
                //检查需要首尾拼接的span内存长度是否足够,不够就扩容
                if (this._takePtrLength == 0)
                {
                    this._takePtr = (T*)NativeMemory.Alloc(byteLength);
                }
                else
                {
                    void* newPtr = NativeMemory.Realloc(this._takePtr, byteLength);
                    if (newPtr == null)
                    {
                        throw new ArgumentException("申请内存失败");
                    }
                    this._takePtr = (T*)newPtr;
                }
            }

            long secondPartLength = this._writeIndex;
            nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
            long firstPartLength = length - secondPartLength;

            //先读取第二部分数据
            NativeMemory.Copy(this._dataPtr, this._takePtr + firstPartLength, secondPartByteLength);

            //再读第一部分数据            
            NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, this._takePtr, byteLength - secondPartByteLength);
            return new SpanZ<T>(this._takePtr, length);
        }




        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns>数据</returns>
        public T[] Peek(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            var data = new T[length];

            fixed (T* ptr = data)
            {
                long modLength = this._capcity - this._readIndex;
                if (modLength >= length)
                {
                    //从读取位置到结尾足够
                    NativeMemory.Copy(this._dataPtr + this._readIndex, ptr, byteLength);
                }
                else
                {
                    nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                    //先读取数组后面的
                    NativeMemory.Copy(this._dataPtr + this._readIndex, ptr, modByteLength);

                    //读取位置归0，再重头读取剩余长度的数据
                    NativeMemory.Copy(this._dataPtr, ptr + modLength, byteLength - modByteLength);
                }
            }

            return data;
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns>数据</returns>
        public T[] PeekTail(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            var data = new T[length];

            fixed (T* ptr = data)
            {
                if (this._writeIndex >= length)
                {
                    NativeMemory.Copy(this._dataPtr + this._writeIndex - length, ptr, byteLength);
                }
                else
                {
                    long secondPartLength = this._writeIndex;
                    nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                    long firstPartLength = length - secondPartLength;

                    //先读取第二部分数据
                    NativeMemory.Copy(this._dataPtr, ptr + firstPartLength, secondPartByteLength);

                    //再读第一部分数据
                    NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, ptr, byteLength - secondPartByteLength);
                }
            }

            return data;
        }





        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns>数据</returns>
        public T[] Peek(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            var data = new T[length];

            fixed (T* ptr = data)
            {
                long modLength = this._capcity - this._readIndex;
                if (modLength >= length)
                {
                    //从读取位置到结尾足够
                    NativeMemory.Copy(this._dataPtr + this._readIndex, ptr, byteLength);
                }
                else
                {
                    nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                    //先读取数组后面的
                    NativeMemory.Copy(this._dataPtr + this._readIndex, ptr, modByteLength);

                    //读取位置归0，再重头读取剩余长度的数据
                    NativeMemory.Copy(this._dataPtr, ptr + modLength, byteLength - modByteLength);
                }
            }

            return data;
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="length">获取数据长度</param>
        /// <returns>数据</returns>
        public T[] PeekTail(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            var data = new T[length];

            fixed (T* ptr = data)
            {
                if (this._writeIndex >= length)
                {
                    NativeMemory.Copy(this._dataPtr + this._writeIndex - length, ptr, byteLength);
                }
                else
                {
                    long secondPartLength = this._writeIndex;
                    nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                    long firstPartLength = length - secondPartLength;

                    //先读取第二部分数据
                    NativeMemory.Copy(this._dataPtr, ptr + firstPartLength, secondPartByteLength);

                    //再读第一部分数据            
                    NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, ptr, byteLength - secondPartByteLength);
                }
            }

            return data;
        }





        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="destinationArray">目标数组</param>
        /// <param name="destinationIndex">目标数组起始位置</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void Peek(T[] destinationArray, int destinationIndex, int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationArray == null)
            {
                throw new ArgumentNullException(nameof(destinationArray));
            }

            if (destinationIndex >= destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            long endIndex = (long)destinationIndex + (long)length;
            if (endIndex > destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));

            fixed (T* ptr = destinationArray)
            {
                T* destPtr = ptr + destinationIndex;
                long modLength = this._capcity - this._readIndex;
                if (modLength >= length)
                {
                    //从读取位置到结尾足够
                    NativeMemory.Copy(this._dataPtr + this._readIndex, destPtr, byteLength);
                }
                else
                {
                    nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                    //先读取数组后面的
                    NativeMemory.Copy(this._dataPtr + this._readIndex, destPtr, modByteLength);

                    //读取位置归0，再重头读取剩余长度的数据
                    NativeMemory.Copy(this._dataPtr, ptr + modLength, byteLength - modByteLength);
                }
            }
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="destinationArray">目标数组</param>
        /// <param name="destinationIndex">目标数组起始位置</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void PeekTail(T[] destinationArray, int destinationIndex, int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationArray == null)
            {
                throw new ArgumentNullException(nameof(destinationArray));
            }

            if (destinationIndex >= destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            long endIndex = (long)destinationIndex + (long)length;
            if (endIndex > destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));

            fixed (T* ptr = destinationArray)
            {
                T* destPtr = ptr + destinationIndex;
                if (this._writeIndex >= length)
                {
                    NativeMemory.Copy(this._dataPtr + this._writeIndex - length, destPtr, byteLength);
                }
                else
                {
                    long secondPartLength = this._writeIndex;
                    nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                    long firstPartLength = length - secondPartLength;

                    //先读取第二部分数据
                    NativeMemory.Copy(this._dataPtr, destPtr + firstPartLength, secondPartByteLength);

                    //再读第一部分数据            
                    NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, destPtr, byteLength - secondPartByteLength);
                }
            }
        }





        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="destinationArray">目标数组</param>
        /// <param name="destinationIndex">目标数组起始位置</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void Peek(T[] destinationArray, long destinationIndex, long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationArray == null)
            {
                throw new ArgumentNullException(nameof(destinationArray));
            }

            if (destinationIndex >= destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            long endIndex = (long)destinationIndex + (long)length;
            if (endIndex > destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));

            fixed (T* ptr = destinationArray)
            {
                T* destPtr = ptr + destinationIndex;
                long modLength = this._capcity - this._readIndex;
                if (modLength >= length)
                {
                    //从读取位置到结尾足够
                    NativeMemory.Copy(this._dataPtr + this._readIndex, destPtr, byteLength);
                }
                else
                {
                    nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                    //先读取数组后面的
                    NativeMemory.Copy(this._dataPtr + this._readIndex, destPtr, modByteLength);

                    //读取位置归0，再重头读取剩余长度的数据
                    NativeMemory.Copy(this._dataPtr, ptr + modLength, byteLength - modByteLength);
                }
            }
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="destinationArray">目标数组</param>
        /// <param name="destinationIndex">目标数组起始位置</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void PeekTail(T[] destinationArray, long destinationIndex, long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationArray == null)
            {
                throw new ArgumentNullException(nameof(destinationArray));
            }

            if (destinationIndex >= destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            long endIndex = (long)destinationIndex + (long)length;
            if (endIndex > destinationArray.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));

            fixed (T* ptr = destinationArray)
            {
                T* destPtr = ptr + destinationIndex;
                if (this._writeIndex >= length)
                {
                    NativeMemory.Copy(this._dataPtr + this._writeIndex - length, destPtr, byteLength);
                }
                else
                {
                    long secondPartLength = this._writeIndex;
                    nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                    long firstPartLength = length - secondPartLength;

                    //先读取第二部分数据
                    NativeMemory.Copy(this._dataPtr, destPtr + firstPartLength, secondPartByteLength);

                    //再读第一部分数据            
                    NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, destPtr, byteLength - secondPartByteLength);
                }
            }
        }





        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="destinationPtr">目标指针</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void Peek(T* destinationPtr, int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationPtr == null)
            {
                throw new ArgumentNullException(nameof(destinationPtr));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                NativeMemory.Copy(this._dataPtr + this._readIndex, destinationPtr, byteLength);
            }
            else
            {
                nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                //先读取数组后面的
                NativeMemory.Copy(this._dataPtr + this._readIndex, destinationPtr, modByteLength);

                //读取位置归0，再重头读取剩余长度的数据
                NativeMemory.Copy(this._dataPtr, destinationPtr + modLength, byteLength - modByteLength);
            }
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="destinationPtr">目标数组</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void PeekTail(T* destinationPtr, int length)
        {
            if (destinationPtr == null)
            {
                throw new ArgumentNullException(nameof(destinationPtr));
            }

            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._writeIndex >= length)
            {
                NativeMemory.Copy(this._dataPtr + this._writeIndex - length, destinationPtr, byteLength);
            }
            else
            {
                long secondPartLength = this._writeIndex;
                nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                long firstPartLength = length - secondPartLength;

                //先读取第二部分数据
                NativeMemory.Copy(this._dataPtr, destinationPtr + firstPartLength, secondPartByteLength);

                //再读第一部分数据            
                NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, destinationPtr, byteLength - secondPartByteLength);
            }
        }





        /// <summary>
        /// 获取起始位置的数据
        /// </summary>
        /// <param name="destinationPtr">目标指针</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void Peek(T* destinationPtr, long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            if (destinationPtr == null)
            {
                throw new ArgumentNullException(nameof(destinationPtr));
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                //从读取位置到结尾足够
                NativeMemory.Copy(this._dataPtr + this._readIndex, destinationPtr, byteLength);
            }
            else
            {
                nuint modByteLength = new nuint((ulong)(modLength * this._TSize));
                //先读取数组后面的
                NativeMemory.Copy(this._dataPtr + this._readIndex, destinationPtr, modByteLength);

                //读取位置归0，再重头读取剩余长度的数据
                NativeMemory.Copy(this._dataPtr, destinationPtr + modLength, byteLength - modByteLength);
            }
        }

        /// <summary>
        /// 获取结束位置的数据
        /// </summary>
        /// <param name="destinationPtr">目标数组</param>
        /// <param name="length">获取数据长度</param>
        /// <exception cref="ArgumentOutOfRangeException">参数越界异常</exception>
        public void PeekTail(T* destinationPtr, long length)
        {
            if (destinationPtr == null)
            {
                throw new ArgumentNullException(nameof(destinationPtr));
            }

            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},获取数据长度:{length}");
            }

            nuint byteLength = new nuint((ulong)(length * this._TSize));
            if (this._writeIndex >= length)
            {
                NativeMemory.Copy(this._dataPtr + this._writeIndex - length, destinationPtr, byteLength);
            }
            else
            {
                long secondPartLength = this._writeIndex;
                nuint secondPartByteLength = new nuint((ulong)(secondPartLength * this._TSize));
                long firstPartLength = length - secondPartLength;

                //先读取第二部分数据
                NativeMemory.Copy(this._dataPtr, destinationPtr + firstPartLength, secondPartByteLength);

                //再读第一部分数据            
                NativeMemory.Copy(this._dataPtr + this._capcity - firstPartLength, destinationPtr, byteLength - secondPartByteLength);
            }
        }

        #endregion





        /// <summary>
        /// 移除位于始位位置指定长度的数据
        /// </summary>
        /// <param name="length">要忽略的数据长度</param>
        public void Remove(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},移除数据长度:{length}");
            }

            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                this._readIndex += length;
            }
            else
            {
                //读取位置归0，再重头读取剩余长度的数据
                this._readIndex = length - modLength;
            }

            this._length -= length;
        }

        /// <summary>
        /// 移除位于始位位置指定长度的数据
        /// </summary>
        /// <param name="length">要忽略的数据长度</param>
        public void Remove(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},移除数据长度:{length}");
            }

            long modLength = this._capcity - this._readIndex;
            if (modLength >= length)
            {
                this._readIndex += length;
            }
            else
            {
                //读取位置归0，再重头读取剩余长度的数据
                this._readIndex = length - modLength;
            }

            this._length -= length;
        }

        /// <summary>
        /// 移除位于尾部位置指定长度的数据
        /// </summary>
        /// <param name="length">要忽略的数据长度</param>
        public void RemoveTail(int length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},移除数据长度:{length}");
            }

            if (this._writeIndex >= length)
            {
                this._writeIndex -= length;
            }
            else
            {
                //再读取数组后面的
                this._writeIndex = this._capcity - (length - this._writeIndex);
            }

            this._length -= length;
        }


        /// <summary>
        /// 移除位于尾部位置指定长度的数据
        /// </summary>
        /// <param name="length">要忽略的数据长度</param>
        public void RemoveTail(long length)
        {
            if (this._length < length)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"当前数据长度:{this._length},移除数据长度:{length}");
            }

            if (this._writeIndex >= length)
            {
                this._writeIndex -= length;
            }
            else
            {
                //再读取数组后面的
                this._writeIndex = this._capcity - (length - this._writeIndex);
            }

            this._length -= length;
        }





        /// <summary>
        /// 清空数据
        /// </summary>
        public void Clear()
        {
            this._readIndex = 0;
            this._writeIndex = 0;
            this._length = 0;
        }


        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            if (this._dataPtr != null)
            {
                NativeMemory.Free(this._dataPtr);
                this._dataPtr = null;
                this._capcity = 0L;
            }

            if (this._takePtr != null)
            {
                NativeMemory.Free(this._takePtr);
                this._takePtr = null;
                this._takePtrLength = 0L;
            }
        }
    }



    unsafe internal sealed class ValueTypeDataMergerDebugView<T> where T : struct
    {
        private readonly T* _ptr;
        private readonly long _length;

        public ValueTypeDataMergerDebugView(ValueTypeDataMerger<T> dataMerger)
        {
            SpanZ<T> span = dataMerger.PeekSpanZ(dataMerger.LongLength);
            this._ptr = span.DataPtr;
            this._length = span.LongLength;
        }


        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        public T[] Items
        {
            get
            {
                T[] array = new T[this._length];
                fixed (T* ptr = array)
                {
                    NativeMemory.Copy(this._ptr, ptr, new nuint((ulong)(this._length * sizeof(T))));
                }
                return array;
            }
        }
    }

}
